package com.liang.manage.auth.facade.server.iml;

import com.liang.manage.auth.facade.dto.org.OrgDTO;
import com.liang.manage.auth.facade.dto.org.OrgOutDTO;
import com.liang.manage.auth.facade.entity.OrgPo;
import com.liang.manage.auth.facade.entity.OrgPoExample;
import com.liang.manage.auth.facade.mapper.OrgPoMapper;
import com.liang.manage.auth.facade.mapstruct.OrgMS;
import com.liang.manage.auth.facade.mapstruct.OrgOutMS;
import com.liang.manage.auth.facade.server.OrgService;

import com.liang.nansheng.common.auth.UserSsoDTO;
import com.liang.nansheng.common.enums.ResponseCode;
import com.liang.nansheng.common.web.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * @author 王华安
 * @date 2021-04-21 20:32
 */
@Slf4j
@Component
@Service
public class OrgServiceImpl implements OrgService {
    @Autowired
    private OrgPoMapper orgPoMapper;

    /**
     * 创建组织架构
     *
     * @param orgDTO
     * @param currentUser
     * @return
     */
    @Override
    public Boolean create(OrgDTO orgDTO, UserSsoDTO currentUser) {
        if (StringUtils.isBlank(orgDTO.getCode()) || StringUtils.isBlank(orgDTO.getName())) {
            throw BusinessException.build(ResponseCode.NOT_EXISTS, "参数不合规");
        }
        if (isNameExist(null, orgDTO.getCode(), orgDTO.getName())) {
            throw BusinessException.build(ResponseCode.NAME_EXIST, "组织架构代码/名称重复");
        }
        // 系统层
        if (orgDTO.getPreId() == null) {
            orgDTO.setPreId(0);
        }
        orgDTO.setCreateUser(currentUser.getUserId());
        orgDTO.setUpdateUser(currentUser.getUserId());
        LocalDateTime now = LocalDateTime.now();
        orgDTO.setCreateTime(now);
        orgDTO.setUpdateTime(now);
        orgDTO.setIsDeleted(false);
        OrgPo orgPo = OrgMS.INSTANCE.toPo(orgDTO);

        Boolean a = orgPoMapper.insertSelective(orgPo) > 0;
        // 通过id创建path
        Boolean b = savePath(orgPo.getId());

        return a && b;
    }

    /**
     * 获取组织架构树
     *
     * @return
     */
    @Override
    public List<OrgOutDTO> getList() {
        OrgPoExample example = new OrgPoExample();
        OrgPoExample.Criteria criteria = example.createCriteria();
        criteria.andIsDeletedEqualTo(false);
        example.setOrderByClause("`id` desc");
        List<OrgPo> orgPos = orgPoMapper.selectByExample(example);

        return generateTree(OrgOutMS.INSTANCE.toDTO(orgPos));
    }

    /**
     * 删除组织架构
     *
     * @param id
     * @param path
     * @return
     */
    @Override
    public Boolean delete(Integer id, String path, UserSsoDTO currentUser) {
        if (StringUtils.isBlank(path)) {
            throw BusinessException.build(ResponseCode.NOT_EXISTS, "参数不合规");
        }
        OrgPoExample example = new OrgPoExample();
        OrgPoExample.Criteria criteria = example.createCriteria();
        criteria.andPathLike("%" + path + "%")
                .andIsDeletedEqualTo(false);
        List<OrgPo> orgPos = orgPoMapper.selectByExample(example);
        for (OrgPo orgPo : orgPos) {
            orgPo.setIsDeleted(true);
            orgPo.setUpdateTime(LocalDateTime.now());
            orgPo.setUpdateUser(currentUser.getUserId());
            orgPoMapper.updateByPrimaryKeySelective(orgPo);
        }
        if (CollectionUtils.isEmpty(orgPos)) {
            throw BusinessException.build(ResponseCode.OPERATE_FAIL, "删除失败");
        }

        return true;
    }

    /**
     * 通过id创建path
     *
     * @param id
     * @return
     */
    @Override
    public Boolean savePath(Integer id) {
        OrgDTO orgDTO = new OrgDTO();
        orgDTO.setId(id);
        // 获取本组织架构信息
        OrgPo orgPo = orgPoMapper.selectByPrimaryKey(id);
        // 获取父组织架构信息
        OrgPo preOrgPo = orgPoMapper.selectByPrimaryKey(orgPo.getPreId());
        if (preOrgPo != null) {
            orgDTO.setPath(preOrgPo.getPath());
        }
        orgDTO.setPath((StringUtils.isEmpty(orgDTO.getPath()) ? "" : orgDTO.getPath()) + "/" + id);

        return orgPoMapper.updateByPrimaryKeySelective(OrgMS.INSTANCE.toPo(orgDTO)) > 0;
    }

    /**
     * 获取组织架构树子节点
     *
     * @param preId
     * @return
     */
    @Override
    public List<OrgOutDTO> getTreeChildNodes(Integer preId) {
        OrgPoExample example = new OrgPoExample();
        example.createCriteria().andIsDeletedEqualTo(false)
                .andPreIdEqualTo(preId);

        return OrgOutMS.INSTANCE.toDTO(orgPoMapper.selectByExample(example));
    }

    /**
     * 通过id获取组织架
     *
     * @param id
     * @return
     */
    @Override
    public OrgOutDTO getById(Integer id) {
        return OrgOutMS.INSTANCE.toDTO(orgPoMapper.selectByPrimaryKey(id));
    }

    /**
     * 生成树
     *
     * @param treeNodes
     */
    private List<OrgOutDTO> generateTree(List<OrgOutDTO> treeNodes) {
        List<OrgOutDTO> trees = new ArrayList<>();
        for (OrgOutDTO treeNode : treeNodes) {
            if (treeNode.getPreId() == 0) {
                trees.add(findChildren(treeNode, treeNodes));
            }
        }
        return trees;
    }

    /**
     * 递归查找子节点
     *
     * @param treeNodes
     * @return
     */
    public static OrgOutDTO findChildren(OrgOutDTO treeNode, List<OrgOutDTO> treeNodes) {
        for (OrgOutDTO orgOutDTO : treeNodes) {
            // 保证每一个叶子节点都不会返回null
            if (CollectionUtils.isEmpty(treeNode.getChildren())) {
                treeNode.setChildren(new ArrayList<>());
            }
            if (treeNode.getId().equals(orgOutDTO.getPreId())) {
                treeNode.getChildren().add(findChildren(orgOutDTO, treeNodes));
            }
        }
        return treeNode;
    }

    /**
     * 判断组织架构是否已经存在
     *
     * @param orgId 组织架构id
     * @param code  组织架构代码
     * @param name  组织架构名称
     * @return
     */
    private boolean isNameExist(Integer orgId, String code, String name) {
        OrgPoExample example = new OrgPoExample();
        // 组织架构代码或名称 ( a = ? and b = ? ) or ( a = ? and c = ? )
        example.or().andIsDeletedEqualTo(false)
                .andCodeEqualTo(code);
        example.or().andIsDeletedEqualTo(false)
                .andNameEqualTo(name);
        List<OrgPo> orgPos = orgPoMapper.selectByExample(example);
        if (orgPos.size() > 1) {
            return true;
        } else if (orgPos.size() == 1) {
            // 更新时orgId是有值的
            return !orgPos.get(0).getId().equals(orgId);
        }
        return false;
    }

}
